/*
 * UARTDriver.cpp
 *
 *  Created on: Jun 4, 2016
 *      Author: Yang
 */

#include <stdio.h>
#include <stdarg.h>

#include "UARTDriver.hpp"

void USART_DARIVER::printf(char* fmt, ...)
{
    double vargflt = 0;
    int vargint = 0;
    char vargch = 0;
    char* vargpch = NULL;
    char* pfmt = NULL;
    va_list vp;

    va_start(vp, fmt);
    pfmt = fmt;

    while (*pfmt)
    {
        if (*pfmt == '%')
        {
            switch (*(++pfmt))
            {

            case 'c':
                vargch = va_arg(vp, int);
                /*    va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                 mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                printch(vargch);
                break;
            case 'd':
            case 'i':
                vargint = va_arg(vp, int);
                printdec(vargint);
                if (vargint == 0)
                {
                    printch((char) '0');
                }
                break;
            case 'f':
                vargflt = va_arg(vp, double);
                /*    va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                 mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                printflt(vargflt);
                break;
            case 's':
                vargpch = va_arg(vp, char*);
                printstr(vargpch);
                break;
            case 'b':
            case 'B':
                vargint = va_arg(vp, int);
                printbin(vargint);
                break;
            case 'x':
            case 'X':
                vargint = va_arg(vp, int);
                printhex(vargint);
                break;
            case '%':
                printch('%');
                break;
            default:
                break;
            }
            pfmt++;
        }
        else
        {
            printch(*pfmt++);
        }
    }
    va_end(vp);
}

void USART_DARIVER::printch(char ch)
{
    uint8_t cha = (uint8_t) ch;
    uint8_t* pcha = &cha;
    HAL_UART_Transmit(&port, pcha, 1, 10);
}

void USART_DARIVER::printdec(int dec)
{
    if (dec == 0)
    {
        return;
    }
    printdec(dec / 10);
    printch((char) (dec % 10 + '0'));
}

void USART_DARIVER::printflt(double flt)
{
    int tmpint = 0;
    if (flt < 0)
    {
        printch((char) '-');
        flt = -flt;
    }
    tmpint = (int) flt;
    if (tmpint == 0)
        printch((char) '0');
    printdec(tmpint);
    flt = flt - (double)tmpint;
    if (flt != 0)
        printch('.');
    for(int i=0;i<6;i++)
    {
    	flt*=10.f;
    	tmpint=(int)(flt);
        if (tmpint == 0)
            printch((char) '0');
		printdec(tmpint);
		flt = flt - (double)tmpint;
    }
}

void USART_DARIVER::printstr(char* str)
{
    while (*str)
    {
        printch(*str++);
    }
}

void USART_DARIVER::printbin(int bin)
{
    if (bin == 0)
    {
        printstr((char*) "0b");
        return;
    }
    printbin(bin / 2);
    printch((char) (bin % 2 + '0'));
}

void USART_DARIVER::printhex(int hex)
{
    if (hex == 0)
    {
        printstr((char*) "0x");
        return;
    }
    printhex(hex / 16);
    if (hex < 10)
    {
        printch((char) (hex % 16 + '0'));
    }
    else
    {
        printch((char) (hex % 16 - 10 + 'a'));
    }
}

void USART_DARIVER::Transmit(uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    HAL_UART_Transmit(&port, pData, Size, Timeout);
}

